package br.com.localfloripa.entities;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PrePersist;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.IndexColumn;
import org.primefaces.model.map.DefaultMapModel;
import org.primefaces.model.map.LatLng;
import org.primefaces.model.map.MapModel;
import org.primefaces.model.map.Marker;

import br.com.localfloripa.services.GeoCodingService;

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="tp_anuncio", discriminatorType=DiscriminatorType.CHAR)
@DiscriminatorValue(value="P")
@Table(name="anuncio")
public class Anuncio implements Serializable {
	
	private static final long serialVersionUID = 8313837081788818968L;
	
	@SequenceGenerator(name="Anuncio_Seq",sequenceName="anuncio_seq")
	@Id @GeneratedValue(generator="Anuncio_Seq")
	private Long id;
	@ManyToOne(optional=true)
	@JoinColumn(name="representante_id",referencedColumnName="id")
	private Representante representante;
	@ManyToOne(optional=false)
	@JoinColumn(name="ramo_id",referencedColumnName="id")
	private Ramo ramo;
	@ManyToOne(optional=false)
	@JoinColumn(name="servico_id",referencedColumnName="id")
	private Servico servico;
	@OneToOne(optional=false,cascade=CascadeType.ALL)
	@JoinColumn(name="empresa_id")
	private Empresa empresa;	
	@ManyToOne(optional=false)
	@JoinColumn(name="cliente_id",referencedColumnName="id")	
	private Cliente cliente;
	@Column(name="ativo",nullable=false)
	private Boolean ativo;
	@Column(name="descricao",nullable=false,length=255)
	private String descricao;	
	@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL,orphanRemoval=true)
	@JoinTable(name="album",joinColumns={@JoinColumn(name="anuncio_id")},inverseJoinColumns={@JoinColumn(name="fotografia_id")})
	private List<Fotografia> album;
	@OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,orphanRemoval=true) 
	@IndexColumn(name="anuncio_avaliacao_id")
	@JoinTable(name="anuncio_avaliacao",joinColumns={@JoinColumn(name="anuncio_id")},inverseJoinColumns={@JoinColumn(name="avaliacao_id")})
	private List<Avaliacao> avaliacoes;
	@Column(name="reputacao_atendimento",nullable=true)
	private Double reputacaoAtendimento;
	@Column(name="reputacao_servico",nullable=true)
	private Double reputacaoServico;
	@OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,orphanRemoval=true)
	@JoinColumn(name="anuncio_id")
	private List<Mensagem> mensagens;	
	@OneToMany(fetch=FetchType.LAZY,targetEntity=Auditoria.class,mappedBy="anuncio")
	private List<Auditoria> auditorias;
	@Column(name="lancamento",nullable=false)
	private Boolean lancamento;
	
	public Anuncio() {
		this.cliente = new Cliente();
		this.ramo = new Ramo();
		this.servico = new Servico();	
		this.empresa = new Empresa();
		this.representante = new Representante();
	}
	
	@PrePersist
	private void prePersist(){
		this.ativo = true;
		this.lancamento = false;
	}
	
	public Representante getRepresentante() {
		return representante;
	}
	public void setRepresentante(Representante representante) {
		this.representante = representante;
	}
	public Ramo getRamo() {
		return ramo;
	}
	public void setRamo(Ramo ramo) {
		this.ramo = ramo;
	}
	public Servico getServico() {
		return servico;
	}
	public void setServico(Servico servico) {
		this.servico = servico;
	}
	public Empresa getEmpresa() {
		return empresa;
	}
	public void setEmpresa(Empresa empresa) {
		this.empresa = empresa;
	}
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public Boolean getAtivo() {
		return ativo;
	}
	public void setAtivo(Boolean ativo) {
		this.ativo = ativo;
	}
	public String getDescricao() {
		return descricao;
	}
	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}
	public Cliente getCliente() {
		return cliente;
	}
	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}

	public List<Fotografia> getAlbum() {
		return album;
	}

	public void setAlbum(List<Fotografia> album) {
		this.album = album;
	}

	public List<Avaliacao> getAvaliacoes() {
		return avaliacoes;
	}

	public void setAvaliacoes(List<Avaliacao> avaliacoes) {
		this.avaliacoes = avaliacoes;
	}

	public Double getReputacaoAtendimento() {
		return reputacaoAtendimento;
	}

	public void setReputacaoAtendimento(Double reputacaoAtendimento) {
		this.reputacaoAtendimento = reputacaoAtendimento;
	}

	public Double getReputacaoServico() {
		return reputacaoServico;
	}

	public void setReputacaoServico(Double reputacaoServico) {
		this.reputacaoServico = reputacaoServico;
	}

	public List<Mensagem> getMensagens() {
		return mensagens;
	}

	public void setMensagens(List<Mensagem> mensagens) {
		this.mensagens = mensagens;
	}

	public List<Auditoria> getAuditorias() {
		return auditorias;
	}

	public void setAuditorias(List<Auditoria> auditorias) {
		this.auditorias = auditorias;
	}

	public Boolean getLancamento() {
		return lancamento;
	}

	public void setLancamento(Boolean lancamento) {
		this.lancamento = lancamento;
	}

	@Transient
	public String getLogo() {
		
		String logo = null;
		for (Fotografia photo : album) {
			if (photo.getLogo()) {
				logo = photo.getThumbImage();
				break;
			}
		}
		if (logo == null) {
			ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageResources");
			logo =  bundle.getString("path.servlet.images.base")+"?photo=noimage";
		}
		return logo;		
	}
	
	@Transient
	public String getLogoLancamento() {
		
		String logo = null;
		for (Fotografia photo : album) {
			if (photo.getLogo()) {
				logo = photo.getPathPreview();
				break;
			}
		}
		if (logo == null) {
			ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageResources");
			logo =  bundle.getString("path.servlet.images.base")+"?photo=noimage";
		}
		return logo;		
	}
	
	
	@Transient
	public Boolean getAlbumIsEmpty() {
		if (this.album != null) {
			return this.album.size() > 0 ? false : true;
		} else {
			return true;
		}
	}
	
	@Transient 
	public String getLocalizacao() {		
		String geocode = null;
		if (this.empresa.getEndereco().getLatitude() != null && this.empresa.getEndereco().getLongitude() != null) {
			geocode = this.empresa.getEndereco().getLatitude()+","+this.empresa.getEndereco().getLongitude();
		} else {
			GeoCodingService geoService = new GeoCodingService();
			Map<String, BigDecimal> localizacao = geoService.geocode(this.empresa.getEndereco());			
			if (localizacao != null && localizacao.size() > 0) {
				geocode = localizacao.get("lat").floatValue()+","+localizacao.get("long").floatValue();
			}
		}		
		return geocode;		
	}
	
	@Transient
	public MapModel getMapModel() {
		
		MapModel mapModel = new DefaultMapModel();
		if (this.empresa.getEndereco().getLatitude() != null && this.empresa.getEndereco().getLongitude() != null) {
			LatLng coord = new LatLng(this.empresa.getEndereco().getLatitude(), this.empresa.getEndereco().getLongitude());
			mapModel.addOverlay(new Marker(coord, this.empresa.getPessoaJuridica().getNome()+" | "+this.empresa.getEndereco().getMunicipio().getNome()+" | "+this.empresa.getEndereco().getBairro()));
		} else {
			GeoCodingService geoService = new GeoCodingService();
			Map<String, BigDecimal> localizacao = geoService.geocode(this.empresa.getEndereco());
			if (localizacao != null && localizacao.size() > 0) {
				LatLng coord = new LatLng(localizacao.get("lat").doubleValue(), localizacao.get("long").doubleValue());
				mapModel.addOverlay(new Marker(coord, this.empresa.getPessoaJuridica().getNome()+" | "+this.empresa.getEndereco().getMunicipio().getNome()+" | "+this.empresa.getEndereco().getBairro()));
			}	
		}
		return mapModel;
	}
	
}
